package top.zywork.jpush;

import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 极光推送工具类<br/>
 * 创建于2020-01-14<br/>
 *
 * @author 王振宇
 * @version 1.0
 */
@Slf4j
public class PushUtils {

    /**
     * 消息推送
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param platform 推送目标平台，直接使用Platform提供的静态方法
     * @param audience 推送目标用户，直接使用Audience提供的静态方法，有alias, tag和regId等模式
     * @param message 推送消息
     * @param extraParams 额外参数
     * @return 返回推送结果对象
     */
    public static PushResult push(PushConfig pushConfig, Platform platform, Audience audience, String message, Map<String, String> extraParams) {
        JPushClient jPushClient = new JPushClient(pushConfig.getMasterSecret(), pushConfig.getAppKey(), null, ClientConfig.getInstance());
        if (extraParams == null) {
            extraParams = new HashMap<>(1);
        }
        PushPayload pushPayload = PushPayload.newBuilder()
                .setPlatform(platform)
                .setAudience(audience)
                .setNotification(Notification.newBuilder()
                        .addPlatformNotification(IosNotification.newBuilder()
                                .setAlert(message)
                                .setBadge(+1)
                                .setSound("happy")
                                .addExtras(extraParams)
                                .build())
                        .addPlatformNotification(AndroidNotification.newBuilder()
                                .setAlert(message)
                                .addExtras(extraParams)
                                .build())
                        .build())
                .setMessage(Message.newBuilder().setMsgContent(message).addExtras(extraParams).build())
                .build();
        try {
            return jPushClient.sendPush(pushPayload);
        } catch (APIConnectionException | APIRequestException e) {
            log.error("jpush message error: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 消息推送，安卓端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param audience 推送目标用户，直接使用Audience提供的静态方法，有alias, tag和regId等模式
     * @param message 推送消息
     * @param extraParams 额外参数
     * @return 返回推送结果对象
     */
    public static PushResult pushAndroid(PushConfig pushConfig, Audience audience, String title, String message, Map<String, String> extraParams) {
        JPushClient jPushClient = new JPushClient(pushConfig.getMasterSecret(), pushConfig.getAppKey(), null, ClientConfig.getInstance());
        if (extraParams == null) {
            extraParams = new HashMap<>(1);
        }
        PushPayload pushPayload = PushPayload.newBuilder()
                .setPlatform(Platform.android())
                .setAudience(audience)
                .setNotification(Notification.android(message, title, extraParams))
                .setMessage(Message.newBuilder().setMsgContent(message).addExtras(extraParams).build())
                .build();
        try {
            return jPushClient.sendPush(pushPayload);
        } catch (APIConnectionException | APIRequestException e) {
            log.error("jpush message error: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 消息推送，苹果端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param audience 推送目标用户，直接使用Audience提供的静态方法，有alias, tag和regId等模式
     * @param message 推送消息
     * @param extraParams 额外参数
     * @return 返回推送结果对象
     */
    public static PushResult pushIos(PushConfig pushConfig, Audience audience, String message, Map<String, String> extraParams) {
        JPushClient jPushClient = new JPushClient(pushConfig.getMasterSecret(), pushConfig.getAppKey(), null, ClientConfig.getInstance());
        if (extraParams == null) {
            extraParams = new HashMap<>(1);
        }
        PushPayload pushPayload = PushPayload.newBuilder()
                .setPlatform(Platform.android())
                .setAudience(audience)
                .setNotification(Notification.newBuilder()
                        .addPlatformNotification(IosNotification.newBuilder()
                                .setAlert(message)
                                .setBadge(+1)
                                .setSound("happy")
                                .addExtras(extraParams)
                                .build())
                        .build())
                .setMessage(Message.newBuilder().setMsgContent(message).addExtras(extraParams).build())
                .build();
        try {
            return jPushClient.sendPush(pushPayload);
        } catch (APIConnectionException | APIRequestException e) {
            log.error("jpush message error: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 消息推送，指定别名
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param platform 推送目标平台，直接使用Platform提供的静态方法
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param alias 推送到的目标用户别名
     * @return 返回推送结果对象
     */
    public static PushResult pushByAlias(PushConfig pushConfig, Platform platform, String message, Map<String, String> extraParams, String alias) {
        return push(pushConfig, platform, Audience.alias(alias), message, extraParams);
    }

    /**
     * 消息推送，指定多个别名
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param platform 推送目标平台，直接使用Platform提供的静态方法
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param aliases 推送到的目标用户别名列表
     * @return 返回推送结果对象
     */
    public static PushResult pushByAlias(PushConfig pushConfig, Platform platform, String message, Map<String, String> extraParams, List<String> aliases) {
        return push(pushConfig, platform, Audience.alias(aliases), message, extraParams);
    }

    /**
     * 消息推送，指定别名，安卓端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param alias 推送到的目标用户别名
     * @return 返回推送结果对象
     */
    public static PushResult pushAndroidByAlias(PushConfig pushConfig, String title, String message, Map<String, String> extraParams, String alias) {
        return pushAndroid(pushConfig, Audience.alias(alias), title, message, extraParams);
    }

    /**
     * 消息推送，指定多个别名，安卓端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param aliases 推送到的目标用户别名列表
     * @return 返回推送结果对象
     */
    public static PushResult pushAndroidByAlias(PushConfig pushConfig, String title, String message, Map<String, String> extraParams, List<String> aliases) {
        return pushAndroid(pushConfig, Audience.alias(aliases), title, message, extraParams);
    }

    /**
     * 消息推送，指定别名，苹果端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param alias 推送到的目标用户别名
     * @return 返回推送结果对象
     */
    public static PushResult pushIosByAlias(PushConfig pushConfig, String message, Map<String, String> extraParams, String alias) {
        return pushIos(pushConfig, Audience.alias(alias), message, extraParams);
    }

    /**
     * 消息推送，指定多个别名，安卓端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param aliases 推送到的目标用户别名列表
     * @return 返回推送结果对象
     */
    public static PushResult pushIosByAlias(PushConfig pushConfig, String message, Map<String, String> extraParams, List<String> aliases) {
        return pushIos(pushConfig, Audience.alias(aliases), message, extraParams);
    }

    /**
     * 消息推送，指定注册id
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param platform 推送目标平台，直接使用Platform提供的静态方法
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param regId 推送到的目标用户注册id
     * @return 返回推送结果对象
     */
    public static PushResult pushByRegId(PushConfig pushConfig, Platform platform, String message, Map<String, String> extraParams, String regId) {
        return push(pushConfig, platform, Audience.registrationId(regId), message, extraParams);
    }

    /**
     * 消息推送，指定多个注册id
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param platform 推送目标平台，直接使用Platform提供的静态方法
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param regIds 推送到的目标用户注册id列表
     * @return 返回推送结果对象
     */
    public static PushResult pushByRegId(PushConfig pushConfig, Platform platform, String message, Map<String, String> extraParams, List<String> regIds) {
        return push(pushConfig, platform, Audience.registrationId(regIds), message, extraParams);
    }

    /**
     * 消息推送，指定注册id，安卓端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param regId 推送到的目标用户注册id
     * @return 返回推送结果对象
     */
    public static PushResult pushAndroidByRegId(PushConfig pushConfig, String title, String message, Map<String, String> extraParams, String regId) {
        return pushAndroid(pushConfig, Audience.registrationId(regId), title, message, extraParams);
    }

    /**
     * 消息推送，指定多个注册id，安卓端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param regIds 推送到的目标用户注册id列表
     * @return 返回推送结果对象
     */
    public static PushResult pushAndroidByRegId(PushConfig pushConfig, String title, String message, Map<String, String> extraParams, List<String> regIds) {
        return pushAndroid(pushConfig, Audience.registrationId(regIds), title, message, extraParams);
    }

    /**
     * 消息推送，指定注册id，苹果端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param regId 推送到的目标用户注册id
     * @return 返回推送结果对象
     */
    public static PushResult pushIosByRegId(PushConfig pushConfig, String message, Map<String, String> extraParams, String regId) {
        return pushIos(pushConfig, Audience.registrationId(regId), message, extraParams);
    }

    /**
     * 消息推送，指定多个注册id，苹果端
     * @param pushConfig 推送配置，包含appKey和masterSecret
     * @param message 推送消息
     * @param extraParams 额外参数
     * @param regIds 推送到的目标用户注册id列表
     * @return 返回推送结果对象
     */
    public static PushResult pushIosByRegId(PushConfig pushConfig, String message, Map<String, String> extraParams, List<String> regIds) {
        return pushIos(pushConfig, Audience.registrationId(regIds), message, extraParams);
    }

}
